﻿/*+===================================================================
File:      Tank.cpp

Summary:   Định nghĩa các phương thức của CTank.
===================================================================+*/

#include "Tank.h"
#include "Explosion.h"
#include "PlayState.h"

#define DIRECTION_LEFT    0
#define DIRECTION_BOT     1
#define DIRECTION_DOWN    2

#define STATUS_STAND      0
#define STATUS_RUN        1
#define VX -100.0f;

CTank::CTank(CBill* bill, D3DXVECTOR2 pos, int id, int typeID) : CMoveableObject(pos, id, typeID)
{
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_1);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_RUN_1);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_1);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_RUN_1);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_1);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_RUN_1);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_2);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_RUN_2);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_2);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_RUN_2);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_2);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_RUN_2);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_3);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_RUN_3);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_3);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_RUN_3);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_3);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_RUN_3);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_4);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_LEFT_RUN_4);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_4);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_BOT_RUN_4);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_4);
	CResourcesManager::GetInstance()->GetSprite(ID_SPRITE_TANK_DOWN_RUN_4);
	m_bill = bill;
	m_nStatus = STATUS_RUN;
	m_nDirection = DIRECTION_LEFT;
	m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_RUN_1);
	m_bCanFire = true;
	m_pGun = new CGun(ID_ENEMY_SMALL_RED_BULLET, 3, 1);
	m_fTimeDie = 0.0f;
	m_nLife = TANK_BLOOD;
	m_v.x = VX;
	m_fTimeFire = 0.3f;
	m_bIsImmortal = true;
	m_pExplosionGroup = new CExplosionGroup(m_pos, id, ID_BIG_EXPLOSION, 0.68f, ID_BIG_EXPLOSION);
	m_pTextureBox = m_pResourceManager->GetTexture(ID_TEXTURE_GROUND_BOX);
}

CTank::~CTank()
{
	if (m_bill)
		delete m_bill;
	if (m_pGun)
		delete m_pGun;
	if (m_pExplosionGroup)
		delete m_pExplosionGroup;
}

void CTank::UpdateAnimation()
{
	if (m_nLife <= 80 && m_nLife > 60)
	{
		switch (m_nStatus)
		{
		case STATUS_RUN:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_RUN_1);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_RUN_1);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_RUN_1);
				break;
			}
			break;
		case STATUS_STAND:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_1);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_1);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_1);
				break;
			}
			break;
		}
	}
	else if (m_nLife <= 60 && m_nLife > 40)
	{
		switch (m_nStatus)
		{
		case STATUS_RUN:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_RUN_2);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_RUN_2);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_RUN_2);
				break;
			}
			break;
		case STATUS_STAND:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_2);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_2);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_2);
				break;
			}
			break;
		}
	}
	else if (m_nLife <= 40 && m_nLife > 20)
	{
		switch (m_nStatus)
		{
		case STATUS_RUN:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_RUN_3);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_RUN_3);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_RUN_3);
				break;
			}
			break;
		case STATUS_STAND:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_3);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_3);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_3);
				break;
			}
			break;
		}
	}
	else
	{
		switch (m_nStatus)
		{
		case STATUS_RUN:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_RUN_4);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_RUN_4);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_RUN_4);
				break;
			}
			break;
		case STATUS_STAND:
			switch (m_nDirection)
			{
			case DIRECTION_LEFT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_LEFT_4);
				break;
			case DIRECTION_BOT:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_BOT_4);
				break;
			case DIRECTION_DOWN:
				m_pSprite = m_pResourceManager->GetSprite(ID_SPRITE_TANK_DOWN_4);
				break;
			}
			break;
		}
	}

}

void CTank::Update(float timeFrame)
{
	if (!m_bIsLive)
	{
		if (m_fTimeDie > 0)
		{
			m_fTimeDie -= timeFrame;
			this->Explode(timeFrame);
		}
		else if (m_fTimeDie < 0)
		{
			m_fTimeDie = 0.0f;
		}
		return;
	}

	if (m_bIsImmortal)
	{
		// Khi tank vào tới giữa màn hình, thì tank dừng lại và đừng đó trong một khoảng thời gian.
		D3DXVECTOR2 tranformPos = CViewport::GetInstance()->TransformMatrix(m_pos);
		if (tranformPos.x - m_pSprite->GetWidth() / 2.0f <= SCREEN_WIDTH / 2.0f)
		{
			m_nStatus = STATUS_STAND;
			m_bIsImmortal = false;
			m_v.x = 0.0f;
			m_fTimeChange = 10.0f;
		}
	}
	else
	{
		// Trong khoảng thời gian tank dừng lại thì tank nhắm bill và bắn
		if (m_fTimeChange > 0)
		{
			m_fTimeChange -= timeFrame;
			D3DXVECTOR2 billPos = m_bill->GetPos();
			// Tính toán vị trí của súng.
			D3DXVECTOR2 gunPos;
			gunPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 45.0f;
			gunPos.y = m_pos.y + m_pSprite->GetHeight() / 2.0f - 25.0f;


			// Tính toán góc của bill so với vị trí súng của tank.
			float angle = atan2(billPos.y - gunPos.y, billPos.x - gunPos.x) * 180 / PI;

			// Tính toán góc bắn và vị trí đạn.
			if (angle < 0 && angle > -135)
			{
				m_nStatusAngle = DIRECTION_DOWN;
				m_pGun->SetBulletAngle(-120);
				m_bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 20.0f;
				m_bulletPos.y = m_pos.y + 10.0f;
			}
			else if (angle < -135 && angle > -165)
			{
				m_nStatusAngle = DIRECTION_BOT;
				m_pGun->SetBulletAngle(-150);
				m_bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f + 10.0f;
				m_bulletPos.y = m_pos.y + 20.0f;
			}
			else
			{
				m_nStatusAngle = DIRECTION_LEFT;
				m_pGun->SetBulletAngle(-180);
				m_bulletPos.x = m_pos.x - m_pSprite->GetWidth() / 2.0f;
				m_bulletPos.y = m_pos.y + m_pSprite->GetHeight() / 2.0f - 24.0f;
			}

			if (m_nDirection > m_nStatusAngle)
				m_nDirection--;
			else if (m_nDirection < m_nStatusAngle)
				m_nDirection++;
		}
		else
		{
			// Hết thời gian tank chạy ra khỏi màn hình.
			m_nStatus = STATUS_RUN;
			m_v.x = VX;
			m_bCanFire = false;
			//Nếu tank chạy ra khỏi màn hình thì Kill
			if (m_pos.x + m_box.width + 30 < CViewport::GetInstance()->GetPosition().x)
			{
				this->Kill();
			}
		}

		//Nếu máu bằng 0 thì chết
		if (m_nLife <= 0)
		{
			this->m_fTimeDie = 0.30f;
			this->Kill();
		}

		if (m_fTimeFire > 0.0f)
		{
			m_fTimeFire -= timeFrame;
		}
		else
		{
			m_fTimeFire = 0.3f;
			if (m_bCanFire)
				if (m_nDirection == m_nStatusAngle)
					m_pGun->Fire(m_bulletPos);
		}
	}

	m_pSprite->Update(timeFrame);
	UpdateAnimation();
	UpdateBox(timeFrame);
}

void CTank::UpdateCollision(vector<CGameObject*> vecGameObjs, float timeFrame)
{
	if (!m_bIsLive && m_fTimeDie == 0.0f)
		return;

	float timeCollision = timeFrame;
	CGameObject* objCollision = NULL; // Đối tượng va chạm sớm nhất.
	float normalx = 0.0f, normaly = 0.0f;

	// Xử lí va chạm với đạn của Bill
	for (int i = 0; i < CPlayState::s_billBullets.size(); i++)
	{
		if (CPlayState::s_billBullets[i]->IsLive())
		{
			float t = CheckCollision(CPlayState::s_billBullets[i], normalx, normaly, timeFrame);

			if (t < timeFrame && t < timeCollision)
			{
				// Tìm đối tượng và thời gian va chạm sớm nhất.
				timeCollision = t;
				objCollision = CPlayState::s_billBullets[i];
			}
		}
	}

	// Xử lí va chạm
	// Kiểm tra Tank có va chạm với đạn của Bill thì giảm máu xuống
	if (objCollision != NULL)
	{
		m_nLife--;
		objCollision->Kill();
	}

	m_v += m_a * timeFrame;
	m_pos += m_v * timeFrame;
}

void CTank::Draw()
{
	if (!m_bIsLive || !m_pSprite)
		return;
	D3DXVECTOR2 pos = CViewport::GetInstance()->TransformMatrix(m_pos);
	m_pSprite->DrawFlipX(pos);
	RECT rect;
	rect.left = m_box.x - m_box.width / 2.0f;
	rect.top = m_box.y + m_box.height / 2.0f;
	rect.right = m_box.x + m_box.width / 2.0f;
	rect.bottom = m_box.y - m_box.height / 2.0f;
	D3DXVECTOR2 pos_box = CViewport::GetInstance()->TransformMatrix(D3DXVECTOR2(m_box.x + m_box.width / 2.0f, m_box.y - m_box.height / 2.0f));
	//m_pTextureBox->DrawRect(pos_box, rect);
}

bool CTank::Kill()
{
	if (m_bIsImmortal)
		return false;

	m_bIsLive = false;
	return true;
}

void CTank::Explode(float timeFrame)
{
	if (m_aPosEx.size() <= 6)
	{ 
		m_aPosEx.push_back(D3DXVECTOR2(m_pos.x - 67.33f, m_pos.y + 16.75f));
		m_aPosEx.push_back(D3DXVECTOR2(m_pos.x, m_pos.y + 16.75f));
		m_aPosEx.push_back(D3DXVECTOR2(m_pos.x + 67.33f, m_pos.y + 16.75f));
		m_aPosEx.push_back(D3DXVECTOR2(m_pos.x - 67.33f, m_pos.y - 16.75f));
		m_aPosEx.push_back(D3DXVECTOR2(m_pos.x, m_pos.y - 16.75f));
		m_aPosEx.push_back(D3DXVECTOR2(m_pos.x + 67.33f, m_pos.y - 16.75f));
		m_pExplosionGroup->SetArrayPos(m_aPosEx);
	}
	m_pExplosionGroup->Update(timeFrame);
}
	
